home *** CD-ROM | disk | FTP | other *** search
- Path: news.mira.net.au!news
- From: davidw@werple.net.au (David White)
- Newsgroups: comp.lang.c++
- Subject: Re: Function returning pointer to equivalent functions
- Date: 20 Feb 1996 21:25:40 +1100
- Organization: Werple Internet, Melbourne
- Message-ID: <4gc7j4$h3s@werple.net.au>
- References: <hesterDn1E2r.K1F@netcom.com>
- NNTP-Posting-Host: werple.mira.net.au
-
- hester@netcom.com (Jim Hester) writes:
-
-
- >I want a group of functions that each can return a pointer to any other
- >function in that group. I can't find any direct way to declare the
- >function's type since the return type ends up in a "recursive" definition
- >loop. I'd prefer to avoid dirty type changes like using void pointers.
-
- >The best that I have done is to envelope the functions in a class and
- >return a pointer to the class (example below). Context: The purpose
- >of these functions is to run an automaton. The main() function below
- >demonstrates it's intended control (except the input char, which SHOULD
- >be pulled from an input stream).
-
- >If states are numbered (as in my unimaginative example below), it's easy
- >to have the functions return indices in an array containing pointers to
- >all of the functions. That's the method I've used in the past. The
- >only problem is that I can't use descriptive state names without going
- >into manually #defining constants for function locations.
-
- >My main question is:
- >Can anyone show me a way of directly declaring the functions to return the
- >pointer I want?
-
- >If not, other suggestions?
-
- >If not, can anybody improve what I have below? The best improvement I
- >can think of is a casting operator from FnEnvelope to pFnEnvelope that
- >would let me forget about adding the '&'s where I need them below.
- >I tried (in public): operator StateType() {return this;}
- >but the compiler didn't like it.
-
- >#include <iostream.h>
-
- >class FnEnvelope;
-
- >typedef StateType (*pStateFn)(char);
-
- >class FnEnvelope
- >{
- > public:
- > FnEnvelope (StateType (*i_F)(char)) : F(i_F) { }
- > StateType Run(char c) { return (*F)(c); }
-
- > private:
- > StateType (*F)(char);
- >};
-
- >StateType State1Fn(char); FnEnvelope State1(State1Fn);
- >StateType State2Fn(char); FnEnvelope State2(State2Fn);
- >FnEnvelope StateQuit(NULL);
-
- >StateType State1Fn(char c)
- >{
- > cout << "this is state1: " << c << endl; // testing
- > switch (c)
- > {
- > case 'e':
- > return &StateQuit;
- > default:
- > return &State2;
- > }
- >}
-
- >StateType State2Fn(char c)
- >{
- > cout << "this is state2: " << c << endl; // testing
- > switch (c)
- > {
- > case 'e':
- > return &StateQuit;
- > default:
- > return &State1;
- > }
- >}
-
- >void main(void)
- >{
- > StateType State;
- > char c = 'a';
- > for ( State = &State1 ; State != &StateQuit ; State = State->Run(c++) );
- >}
-
-
- An interesting problem. All declarations, no matter how complex, must end
- in some type that is not derived from some other, i.e., no matter how
- many (), or *, or [] there are in any declaration, it eventually has to
- end in something such as 'int', 'char' or 'MyClass'. This fact, as you
- have discovered, appears to rule out the possibility of declaring the
- type you want directly. I would be tempted to just use a void *, because
- it would probably need a cast in only one place. In your example, you
- could remove the '&'s, at least where they are :), by using references
- instead of pointers, i.e., typedef StateType (&pStateFn)(char);
-
- One different approach is demonstrated in the code below. It effectively
- replaces your Run() transfer function with a virtual function call.
-
- #include <iostream.h>
-
- struct Automaton;
-
- struct BaseState
- {
- BaseState(Automaton &a) : automaton(a) {}
- virtual BaseState *Run(char c) = 0;
- protected:
- Automaton &automaton;
- };
-
- struct State1 : public BaseState
- {
- State1(Automaton &a) : BaseState(a) {}
- BaseState *Run(char c);
- };
-
- struct State2 : public BaseState
- {
- State2(Automaton &a) : BaseState(a) {}
- BaseState *Run(char c);
- };
-
- struct QuitState : public BaseState
- {
- QuitState(Automaton &a) : BaseState(a) {}
- BaseState *Run(char c) { return 0; }
- };
-
- struct Automaton
- {
- State1 *state1;
- State2 *state2;
- QuitState *quitState;
- };
-
-
- BaseState *State1::Run(char c)
- {
- cout << "this is state1: " << c << endl; // testing
- switch (c)
- {
- case 'e':
- return automaton.quitState;
- default:
- return automaton.state2;
- }
- }
-
- BaseState *State2::Run(char c)
- {
- cout << "this is state2: " << c << endl; // testing
- switch (c)
- {
- case 'e':
- return automaton.quitState;
- default:
- return automaton.state1;
- }
- }
-
- int main()
- {
- Automaton a;
- State1 state1(a);
- State2 state2(a);
- QuitState quitState(a);
- a.state1 = &state1;
- a.state2 = &state2;
- a.quitState = &quitState;
-
- BaseState *state = &state1;
- char c = 'a';
- while(state)
- {
- state = state->Run(c++);
- }
- return 0;
- }
-
- David White
- davidw@werple.mira.net.au
-